# _*_ coding:utf-8 _*_
# @Time  : 2023.01.09
# @Author: zizlee
import json
import pathlib
import datetime
import smtplib
import shutil
import sys
import time
import threading
import tkinter as tk
import tkinter.messagebox
from tkinter import ttk
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication


class EmailSender(object):
    def __init__(self, smtp_host, smtp_port, user, psd, sender, receives):
        self.smtp_host = smtp_host
        self.smtp_port = smtp_port
        self.user = user
        self.psd = psd
        self.sender = sender
        self.receives = receives

        self.smtp_ssl_client = smtplib.SMTP_SSL(self.smtp_host, self.smtp_port)
        self.login_res = self.smtp_ssl_client.login(self.user, self.psd)
        # print('登录成功')

    def send_multipart_email(self, customer_filename, body_text="", annex=None):
        message = MIMEMultipart()
        message['From'] = self.sender
        message['To'] = ",".join(self.receives)
        message['Subject'] = customer_filename
        message['Accept-Language'] = 'zh-CN'
        message['Accept-Charset'] = 'ISO-8859-1,utf-8'
        # print('From：', self.sender)
        # print('To：', ",".join(self.receives))
        # print('Subject：', customer_filename)

        if not annex:
            return False
        # 正文
        if body_text:
            message.attach(MIMEText(body_text, 'plain', 'utf-8'))
        # 附件
        if annex:
            with open(annex, 'rb') as af:
                att1 = MIMEApplication(af.read())
                att1['Content-Type'] = 'application/octet-stream'
                att1.add_header('Content-Disposition', 'attachment', filename=annex.name)
                message.attach(att1)

        try:
            if self.login_res and self.login_res[0] == 235:
                self.smtp_ssl_client.sendmail(self.sender, self.receives, message.as_string())
                now = datetime.datetime.now()
                with open(f'logs/sent_{now.strftime("%Y%m%d")}.txt', 'a+', encoding='utf8') as f:
                    f.write(f'{now.strftime("%Y-%m-%d %H:%M:%S")} {annex.name}发送至{",".join(self.receives)}\n')
                return True
            else:
                return False
        except Exception as e:
            now = datetime.datetime.now()
            with open(f'logs/error_{now.strftime("%Y%m%d")}.txt', 'a+', encoding='utf8') as f:
                f.write(f'附件:{annex.name},邮件发送失败:{e}\n')
            return False


def read_configs():
    # config_folder = pathlib.Path(__file__).parent
    # config_file = pathlib.Path(config_folder).joinpath('configs.json')
    with open('configs.json', 'r', encoding='utf8') as f:
        configs = json.load(f)

    current_day = configs.get('handleDate', None)
    if not current_day:
        current_day = datetime.datetime.today().strftime('%Y%m%d')
    # 设置缓存的文件夹
    if not configs['pdfRemoveFolder']:
        configs['pdfRemoveFolder'] = configs['pdfFolder'] + f'/myTempFile/{current_day[:6]}'
    tmp = pathlib.Path(configs['pdfRemoveFolder'])
    if not tmp.exists():
        tmp.mkdir(parents=True)
    return configs


def read_pdf_files():
    configs = read_configs()
    current_month = datetime.datetime.today().strftime('%Y-%m')
    current_day = configs.get('handleDate', None)
    if not current_day:
        current_day = datetime.datetime.today().strftime('%Y%m%d')
    # 读取文件
    file_folder = pathlib.Path(configs.get('pdfFolder')).joinpath(current_month)
    variety_dict = configs.get('variety', {})
    group_dict = configs.get('groups', {})
    authors_dict = configs.get('authors', {})
    # 以pdf结尾的
    file_list = []
    for pdf_file in file_folder.glob('*.pdf'):
        # 今日的报告
        filename = pdf_file.name

        if filename.endswith(f'{current_day}.pdf'):
            file_type = None
            if '日报' in filename:
                file_type = '日报'
            if '周报' in filename:
                file_type = '周报'
            if '月报' in filename:
                file_type = '月报'

            variety_en = None
            group_name = None
            author_name = None
            for k, v in variety_dict.items():
                if k in filename:
                    variety_en = v
                    break
            if variety_en:
                group_name = group_dict.get(variety_en)
                author_name = authors_dict.get(variety_en)

            if all([file_type, variety_en, group_name]):
                o_file = {
                    'filepath': pdf_file,
                    'file_type': file_type,
                    'variety_en': variety_en,
                    'group': group_name,
                    'author': author_name,
                    'file_date': current_day
                }
                file_list.append(o_file)
    return file_list


class Window(tk.Tk):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        w, h = self.winfo_screenwidth(), self.winfo_screenheight()
        x, y = int((w - 800) / 2), int((h - 500) / 2)
        self.geometry('800x500+%s+%s' % (x, y))
        self.title('报告邮件发送器')
        self.iconbitmap('favicon.ico')
        self.configs = read_configs()

        self.label1 = tk.Label(self, text='文件地址：')
        self.label1.place(x=30, y=0, width=60, height=30)

        self.label2 = tk.Label(self, text=self.configs['pdfFolder'])
        self.label2.place(x=100, y=0, height=30)

        self.label3 = tk.Label(self, text='邮箱未登录,点击开始自动登录', fg='red')
        self.label3.place(x=30, y=30, height=30)

        self.button1 = tk.Button(self, text='开始运行',
                                 command=self.create_send_thread)
        self.button1.place(x=700, width=70, y=30, height=30)

        self.y_bar = ttk.Scrollbar(self, orient='vertical')

        self.tree = ttk.Treeview(self, show='headings', columns=('日期', '文件', '状态'))
        self.tree.column('日期', width=120, anchor=tk.CENTER)
        self.tree.column('文件', width=400, anchor=tk.CENTER)
        self.tree.column('状态', width=200, anchor=tk.CENTER)
        self.tree.heading('日期', text='日期')
        self.tree.heading('文件', text='文件')
        self.tree.heading('状态', text='状态')

        self.y_bar.configure(command=self.tree.yview)
        self.tree.configure(yscrollcommand=self.y_bar.set)

        self.tree.place(x=30, y=70, width=720, height=400)
        self.y_bar.place(x=750, y=70, height=400)

        self.style = ttk.Style()
        self.style.map("Treeview", foreground=self.fixed_map("foreground"), background=self.fixed_map("background"))


        self.file_list = []
        # 创建logs文件夹
        log_f = pathlib.Path('logs')
        if not log_f.exists():
            log_f.mkdir(parents=True)

    def fixed_map(self, option):  # Returns the style map for 'option' with any styles starting with # ("!disabled", "!selected", ...) filtered out # style.map() returns an empty list for missing options, so this should # be future-safe
        return [elm for elm in self.style.map("Treeview", query_opt=option) if elm[:2] != ("!disabled", "!selected")]

    def add_files(self):
        self.file_list = read_pdf_files()
        for i, file in enumerate(self.file_list):
            item = self.tree.insert('', 'end', iid=str(i + 1), values=[file['file_date'], file['filepath'].name, '待发送'])
            file['t_item'] = item

    def create_send_thread(self):
        if len(self.file_list) < 1:
            tkinter.messagebox.showinfo(title='提示', message='没有检测到文件.')
            return
        t = threading.Thread(target=self.start_send_email)
        t.setDaemon(True)
        t.start()

    def start_send_email(self):
        sender = self.configs['sender']
        email_handler = EmailSender(smtp_host=sender['smtpHost'],
                                    smtp_port=sender['smtpPort'],
                                    user=sender['user'],
                                    psd=sender['password'],
                                    receives=self.configs['receivers'],
                                    sender=sender['name'])
        if email_handler.login_res and email_handler.login_res[0] == 235:
            self.label3.config(fg='green', text='邮箱登录成功')
        else:
            self.label3.config(fg='red', text='邮箱登录失败')
            return
        for i, file in enumerate(self.file_list):
            # 发送
            customer_filename = f'瑞达期货*{file["group"]}*{file["filepath"].name.replace(".pdf", "")}*{file["author"]}{file["file_date"]}'
            is_success = email_handler.send_multipart_email(customer_filename=customer_filename, annex=file['filepath'])
            self.tree.item(str(i + 1), values=[file['file_date'], file['filepath'].name, '发送中...'])
            # is_success = False
            if is_success:
                # 移动文件
                target = pathlib.Path(self.configs['pdfRemoveFolder']).joinpath(file["filepath"].name)
                shutil.move(file["filepath"], target)
                self.tree.item(str(i + 1), values=[file['file_date'], file['filepath'].name, '发送成功'], tags='blueText')
            else:
                self.tree.item(str(i + 1), values=[file['file_date'], file['filepath'].name, '发送失败'], tags='redText')
            time.sleep(self.configs['speed'])

        tkinter.messagebox.showinfo(title='提示', message='数据处理完成.')

        self.destroy()


if __name__ == '__main__':
    root_window = Window()
    root_window.add_files()
    root_window.mainloop()
